---
title: Program Derived Address
description:
  Learn how to use Program Derived Addresses (PDAs) in Anchor programs to create
  deterministic account addresses.
---

Program Derived Addresses (PDA) refer to a feature of Solana development that
allows you to create a unique address derived deterministically from pre-defined
inputs (seeds) and a program ID.

This section will cover basic examples of how to use PDAs in an Anchor program.

## Anchor PDA Constraints

When using PDAs in an Anchor program, you generally use Anchor's account
constraints to define the seeds to derive the PDA. These constraints serve as
security checks to ensure that the correct address is derived.

The constraints used to define the PDA seeds include:

- `seeds`: An array of optional seeds used to derive the PDA. Seeds can be
  static values or dynamic references to account data.
- `bump`: The bump seed used to derive the PDA. Used to ensure the address falls
  off the Ed25519 curve and is a valid PDA.
- `seeds::program` - (Optional) The program ID used to derive the PDA address.
  This constraint is only used to derive a PDA where the program ID is not the
  current program.

<Callout type="info">
  The `seeds` and `bump` constraints are required to be used together.
</Callout>

### Usage Examples

Below are examples demonstrating how to use PDA constraints in an Anchor
program.

<Tabs items={['seeds', 'bump', 'seeds::program', 'init']}>
<Tab value="seeds">

The `seeds` constraint specifies the optional values used to derive the PDA.

#### No Optional Seeds

- Use an empty array `[]` to define a PDA without optional seeds.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    #[account(
        // [!code highlight]
        seeds = [],
        bump,
    )]
    pub pda_account: SystemAccount<'info>,
}
```

#### Single Static Seed

- Specify optional seeds in the `seeds` constraint.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    #[account(
        // [!code word:b"hello_world"]
        // [!code highlight]
        seeds = [b"hello_world"],
        bump,
    )]
    pub pda_account: SystemAccount<'info>,
}
```

#### Multiple Seeds and Account References

- Multiple seeds can be specified in the `seeds` constraint. The `seeds`
  constraint can also reference other account addresses or account data.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    pub signer: Signer<'info>,
    #[account(
        // [!code highlight]
        seeds = [b"hello_world", signer.key().as_ref()],
        bump,
    )]
    pub pda_account: SystemAccount<'info>,
}
```

The example above uses both a static seed (`b"hello_world"`) and a dynamic seed
(the signer's public key).

</Tab>
<Tab value="bump">

The `bump` constraint specifies the bump seed used to derive the PDA.

#### Automatic Bump Calculation

When using the `bump` constraint without a value, the bump is automatically
calculated each time the instruction is invoked.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    #[account(
        seeds = [b"hello_world"],
        // [!code highlight]
        bump,
    )]
    pub pda_account: SystemAccount<'info>,
}
```

#### Specify Bump Value

You can explicitly provide the bump value, which is useful for optimizing
compute unit usage. This assumes that the PDA account has been created and the
bump seed is stored as a field on an existing account.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    #[account(
        seeds = [b"hello_world"],
        // [!code highlight]
        bump = pda_account.bump_seed,
    )]
    pub pda_account: Account<'info, CustomAccount>,
}

#[account]
pub struct CustomAccount {
    pub bump_seed: u8,
}
```

By storing the bump value in the account's data, the program doesn't need to
recalculate it, saving compute units. The saved bump value can be stored on the
account itself or another account.

</Tab>
<Tab value="seeds::program">

The `seeds::program` constraint specifies the program ID used to derive the PDA.
This constraint is only used when deriving a PDA from a different program.

Use this constraint when your instruction needs to interact with PDA accounts
created by another program.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    #[account(
        seeds = [b"hello_world"],
        bump,
        // [!code word:other_program]
        // [!code highlight]
        seeds::program = other_program.key(),
    )]
    pub pda_account: SystemAccount<'info>,
    pub other_program: Program<'info, OtherProgram>,
}
```

</Tab>
<Tab value="init">

The `init` constraint is commonly used with `seeds` and `bump` to create a new
account with an address that is a PDA. Under the hood, the `init` constraint
invokes the System Program to create the account.

```rust
#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    #[account(mut)]
    pub signer: Signer<'info>,
    #[account(
        // [!code word:init]
        // [!code highlight:3]
        init,
        payer = signer,
        space = 8 + 1,
        seeds = [b"hello_world", signer.key().as_ref()],
        bump,
    )]
    pub pda_account: Account<'info, CustomAccount>,
    pub system_program: Program<'info, System>,
}

#[account]
pub struct CustomAccount {
    pub bump_seed: u8,
}
```

<Callout type="info">
  The `init` constraint must be used with `payer` and `space`. The `payer`
  specifies the account that will pay for the account creation. The `space`
  specifies the bytes to allocate for the account (including the 8-byte
  discriminator).
</Callout>

</Tab>
</Tabs>

## PDA seeds in the IDL

Program Derived Address (PDA) seeds defined in the `seeds` constraint are
included in the program's IDL file. This allows the Anchor client to
automatically resolve account addresses using these seeds when constructing
instructions.

This example below shows the relationship between the program, IDL, and client.

<Tabs items={['Program', 'IDL', 'Client']}>
<Tab value="Program">

The program below defines a `pda_account` using a static seed (`b"hello_world"`)
and the signer's public key as a dynamic seed.

```rust
use anchor_lang::prelude::*;

declare_id!("BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5");

#[program]
mod hello_anchor {
    use super::*;
    pub fn test_instruction(ctx: Context<InstructionAccounts>) -> Result<()> {
        msg!("PDA: {}", ctx.accounts.pda_account.key());
        Ok(())
    }
}

#[derive(Accounts)]
pub struct InstructionAccounts<'info> {
    // [!code word:signer]
    pub signer: Signer<'info>,
    #[account(
        // [!code highlight]
        seeds = [b"hello_world", signer.key().as_ref()],
        bump,
    )]
    pub pda_account: SystemAccount<'info>,
}
```

</Tab>
<Tab value="IDL">

The program's IDL file includes the PDA seeds defined in the `seeds` constraint.

- The static seed `b"hello_world"` is converted to byte values.
- The dynamic seed is included as reference to the signer account.

```json
{
  "address": "BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5",
  "metadata": {
    "name": "hello_anchor",
    "version": "0.1.0",
    "spec": "0.1.0",
    "description": "Created with Anchor"
  },
  "instructions": [
    {
      "name": "test_instruction",
      "discriminator": [33, 223, 61, 208, 32, 193, 201, 79],
      "accounts": [
        {
          "name": "signer",
          "signer": true
        },
        {
          "name": "pda_account",
          "pda": {
            // [!code word:seeds]
            "seeds": [
              {
                // [!code highlight:2]
                "kind": "const",
                "value": [104, 101, 108, 108, 111, 95, 119, 111, 114, 108, 100]
              },
              {
                // [!code highlight:2]
                "kind": "account",
                "path": "signer"
              }
            ]
          }
        }
      ],
      "args": []
    }
  ]
}
```

</Tab>
<Tab value="Client">

The Anchor client can automatically resolve the PDA address using the IDL file.

In the example below, Anchor automatically resolves the PDA address using the
provider wallet as the signer, and its public key as the dynamic seed for PDA
derivation. This removes the need to explicitly derive the PDA when building the
instruction.

```ts {13}
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { HelloAnchor } from "../target/types/hello_anchor";

describe("hello_anchor", () => {
  // Configure the client to use the local cluster.
  anchor.setProvider(anchor.AnchorProvider.env());

  const program = anchor.workspace.HelloAnchor as Program<HelloAnchor>;

  it("Is initialized!", async () => {
    // Account address is automatically resolved using the IDL
    const tx = await program.methods.testInstruction().rpc();
    console.log("Your transaction signature", tx);
  });
});
```

When the instruction is invoked, the PDA is printed to program logs as defined
in the program instruction.

```{3}
Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1]
Program log: Instruction: TestInstruction
Program log: PDA: 3Hikt5mpKaSS4UNA5Du1TZJ8tp4o8VC8YWW6X9vtfVnJ
Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 consumed 18505 of 200000 compute units
Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 success
```

</Tab>
</Tabs>
